package com.niiwoo.civet.trade.service.local.newRefund.refundDeal;

import com.alibaba.dubbo.config.annotation.Reference;
import com.niiwoo.civet.account.constant.MQConstant;
import com.niiwoo.civet.account.dto.request.TransFreezeRequestDTO;
import com.niiwoo.civet.account.service.trade.TransOrderDubboService;
import com.niiwoo.civet.base.enums.BorrowProjectTypeEnum;
import com.niiwoo.civet.base.enums.OrderTradeSourceEnum;
import com.niiwoo.civet.base.enums.RefundTypeEnum;
import com.niiwoo.civet.trade.dao.entity.*;
import com.niiwoo.civet.trade.dao.mapper.*;
import com.niiwoo.civet.trade.dto.newRefund.RefundFeeDTO;
import com.niiwoo.civet.trade.dto.newRefund.RefundStateDTO;
import com.niiwoo.civet.trade.enums.RefundOptTypeEnum;
import com.niiwoo.civet.trade.enums.RefundTradeTypeEnum;
import com.niiwoo.civet.trade.service.local.newRefund.refundDeal.core.FeeCalcForRefundService;
import com.niiwoo.civet.trade.service.local.newRefund.refundDeal.core.FreezeDealingService;
import com.niiwoo.civet.trade.service.local.newRefund.refundDeal.core.RefundService;
import com.niiwoo.tripod.provider.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 *  机构代还
 */
@Service
@Slf4j
public class RefundForGuaranteeService {

    @Autowired
    private ProjectMapperExt projectMapperExt;

    @Autowired
    private ProjectBorrowerSummaryMapperExt projectBorrowerSummaryMapperExt;

    @Autowired
    private RefundService refundService;

    @Reference(version = "1.0.0")
    private TransOrderDubboService transOrderDubboService;

    @Autowired
    private FreezeDealingService freezeDealingService;

    @Autowired
    private ProjectInvestorPlanMapperExt projectInvestorPlanMapperExt;

    @Autowired
    private ProjectBorrowerPlanNewMapperExt projectBorrowerPlanNewMapperExt;

    @Autowired
    private FeeCalcForRefundService feeCalcForRefundService;

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private AdvanceConfigMapperExt advanceConfigMapperExt;

    @Transactional(isolation = Isolation.READ_COMMITTED)
    public RefundOrder refund(long projectId, OrderTradeSourceEnum orderTradeSourceEnum, Date currentDate, Date compareDate,
                              String sourceUserId, String sourcePlatformUserNo, Long sourceAccountId){
        try{
            ProjectBorrowerSummary summary = projectBorrowerSummaryMapperExt.selectByPrimaryKeyForUpdate(projectId);
            // 垫付准入检查
            refundService.check(projectId);
            Project project = projectMapperExt.selectByPrimaryKey(projectId);
            if(BorrowProjectTypeEnum.DECORATION_LOAN.getValue().equals(project.getType())){
                log.error("装修借当前不需要还款，projectId=" + projectId);
                throw new BizException("装修借当前不需要还款，projectId=" + projectId);
            }
            AdvanceConfig advanceConfig = advanceConfigMapperExt.selectByPrimaryKey(project.getOrgId());
            if(advanceConfig==null){
                log.error("当前机构不需要垫付，projectId=" + projectId + ",org_id="+project.getOrgId());
                throw new BizException("当前机构不需要垫付，projectId=" + projectId + ",org_id="+project.getOrgId());
            }
            // 获取应垫金额
            List<ProjectInvestorPlan> investorPlans = projectInvestorPlanMapperExt.listProjectPeriodInvestorPlanReceiveDate(projectId, compareDate);
            List<Integer> periodList = new ArrayList<>();//保存待垫付期数
            RefundStateDTO refundStateDTO = new RefundStateDTO();
            for (ProjectInvestorPlan investorPlan : investorPlans) {
                if (investorPlan.getCapital().subtract(investorPlan.getReceivedCapital()).compareTo(BigDecimal.ZERO)>0
                        || investorPlan.getInterest().subtract(investorPlan.getReceivedInterest()).compareTo(BigDecimal.ZERO)>0) {
                    periodList.add(investorPlan.getCurrentPeriod());
                }
                refundStateDTO.setCapital(refundStateDTO.getCapital().add(investorPlan.getCapital()).subtract(investorPlan.getReceivedCapital()));
                refundStateDTO.setInterest(refundStateDTO.getInterest().add(investorPlan.getInterest()).subtract(investorPlan.getReceivedInterest()));
            }
            if(periodList.size()== 0){
                log.error("当前不需要垫付，projectId=" + projectId);
                throw new BizException("当前不需要垫付，projectId=" + projectId);
            }
            // 垫付检查
            List<ProjectBorrowerPlanNew> projectBorrowerPlanNews = projectBorrowerPlanNewMapperExt.selectByProjectIdAndPeriods(projectId, periodList);
            List<RefundFeeDTO> refundingFeeDTOList = feeCalcForRefundService.getRefundingFeeDTOList(projectBorrowerPlanNews, null);
            RefundStateDTO refundStateDTOCheck = feeCalcForRefundService.convertToRefundFee(refundingFeeDTOList);
            if(refundStateDTO.getCapital().compareTo(refundStateDTOCheck.getCapital()) != 0
                    || refundStateDTO.getInterest().compareTo(refundStateDTOCheck.getInterest()) != 0){
                log.error("标的垫付失败，待还和待收金额不匹配，projectId=" + projectId);
                throw new RuntimeException("标的垫付失败，待还和待收金额不匹配，projectId=" + projectId);
            }
            if(Byte.valueOf("1").equals(advanceConfig.getIsAdvanceManagerFee())){
                refundStateDTO.setManageFee(refundStateDTOCheck.getManageFee());
                refundStateDTO.setAmount(refundStateDTO.getAmount().add(refundStateDTOCheck.getManageFee()));
            }
            if(Byte.valueOf("1").equals(advanceConfig.getIsAdvanceConsultingFee())){
                refundStateDTO.setConsultingFee(refundStateDTOCheck.getConsultingFee());
                refundStateDTO.setAmount(refundStateDTO.getAmount().add(refundStateDTOCheck.getConsultingFee()));
            }
            refundStateDTO.setAmount(refundStateDTO.getAmount().add(refundStateDTO.getCapital().add(refundStateDTO.getInterest())));
            if(refundStateDTO.getAmount().compareTo(BigDecimal.ZERO) <= 0){
                log.error("当前不需要垫付，projectId=" + projectId);
                throw new BizException("当前不需要垫付，projectId=" + projectId);
            }

            RefundOrder refundOrder = refundService.createRefundOrder(RefundTypeEnum.IMMEDIATELY, RefundTradeTypeEnum.ADVANCE, orderTradeSourceEnum, refundStateDTO, refundStateDTO,
                    project, sourceAccountId, sourcePlatformUserNo, sourceUserId, currentDate, summary.getRepayStatus(), compareDate, null, RefundOptTypeEnum.BY_COMPARE_DATE,null,null);
            // 发起资金冻结请求
            TransFreezeRequestDTO transFreezeRequestDTO = freezeDealingService.buidTransFreezeRequestDTO(refundOrder, project.getType(), project.getTitle(),
                    summary.getCurrentPeriod(), summary.getTotalPeriod());
            log.info("发送账户中心还款预处理事件MQ,orderId={}",transFreezeRequestDTO.getOrderId());
            rabbitTemplate.convertAndSend(MQConstant.REFUND_FREEZE_EXCHANGE, MQConstant.REFUND_FREEZE_ROUTING, transFreezeRequestDTO);
            return refundOrder;
        } catch (Exception e){
            log.error("垫付创建订单失败:projectId={},orderTradeSourceEnum={},currentDate={},compareDate={}", projectId, orderTradeSourceEnum, currentDate, compareDate);
            throw e;
        }
    }

}
